package com.hsmpay.common.service.impl;

import com.hsmpay.common.service.MemcachedService;
import com.hsmpay.common.util.system.Constant;
import net.rubyeye.xmemcached.GetsResponse;
import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.exception.MemcachedException;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;
import java.util.concurrent.TimeoutException;

//import com.wanjx.common.util.memcached.MemcachedUtil;

/**
 * Memcached 顶层服务类接口实现类
 *
 * @param <Entity>
 * @param <Query>
 * @author 颜铃璋
 * @date 2012-12-15
 */
public class MemcachedServiceSupport<Entity extends Serializable, Query extends Object> extends BaseServiceSupport<Entity, Query> implements MemcachedService<Entity, Query> {
    public int EXPIRATION_TIME = Integer.parseInt(Constant.getAttribute("MEMCACHE_EXPIRE"));//子类可能需要修改  所有不声明为final
    private static Logger log = Logger.getLogger(MemcachedServiceSupport.class);
    private boolean retType = true;//××××××默认返回Memcached 所以操作返回×××××××
    /**
     * Memcached 对象
     **/
    @Resource(name = "memcachedClient")
    public MemcachedClient memcachedClient;

//	public MemcachedServiceSupport(){
//		memcachedClient = MemcachedUtil.memcachedFactory();
//	}

    /**
     * 保存 Memcached 节点
     *
     * @param key
     * @param value
     * @return
     * @throws Exception
     */
    private boolean setCacheNode(String key, Object value) throws Exception {
        log.debug("--- setCacheNode() start --- " + EXPIRATION_TIME);
        boolean addType = false;
        Object obj = getCacheNode(key);
        if (null != obj) {//如果存在 就替换
            addType = replaceCacheNode(key, value);
        } else {
            addType = memcachedClient.set(key, EXPIRATION_TIME, value);
        }
        //boolean addType = memcachedClient.set(key, MemcachedConstant.EXPIRATION_TIME, value);
        return addType;
    }

    /**
     * 获得 Memcached 节点对象
     *
     * @param cacheKey
     * @return
     * @throws Exception
     */
    private Object getCacheNode(String cacheKey) throws Exception {
        log.debug("--- getCacheNode() start ---");
        //return memcachedClient.getAndTouch(cacheKey, EXPIRATION_TIME);
        return memcachedClient.get(cacheKey, EXPIRATION_TIME);
    }

    /**
     * 获得 Memcached 节点对象
     *
     * @param key
     * @return
     * @throws Exception
     */
    public Object getCacheData(String key) throws Exception {
        log.debug("--- getCacheData() start ---");
        Object resData = null;
        try {
            if (StringUtils.isNotEmpty(key)) {
                resData = getCacheNode(key);
            }
        } catch (Exception e) {
            log.error("###MemcachedClient is no available connection at this moment###");
        }
        return resData;
    }

    /**
     * 保存 Memcached 数据
     *
     * @param key
     * @param rootDate
     * @return
     * @throws Exception
     */
    public boolean setCacheData(String key, Object rootDate) throws Exception {
        log.debug("--- setCacheNode() start ---");
        boolean retType = this.retType;
        try {
            if (StringUtils.isNotEmpty(key)) {
                retType = setCacheNode(key, rootDate);
            }
        } catch (Exception e) {
            log.error("###MemcachedClient is no available connection at this moment###");
        }
        return retType;
    }

    /**
     * 保存 Memcached 列表
     *
     * @param key
     * @return
     * @throws Exception
     */
    public boolean setCacheList(String key, List<Entity> retEntity) throws Exception {
        log.debug("--- setCacheList() start ---");
        boolean retType = this.retType;
        try {
            if (null != retEntity && retEntity.size() > 0) {
                retType = setCacheNode(key, retEntity);
            }
        } catch (Exception e) {
            log.error("###MemcachedClient is no available connection at this moment###");
        }
        return retType;
    }

    /**
     * 判断key对应的 Memcached 节点对象是否存在
     *
     * @param key
     * @return
     * @throws Exception
     */
    public boolean existCacheNode(String key) throws Exception {
        log.debug("--- existCacheNode() start ---");
        boolean keyExists = false;
        try {
            if (StringUtils.isNotEmpty(key)) {
                if (getCacheNode(key) != null) {
                    keyExists = true;
                }
            }
        } catch (Exception e) {
            log.error("###MemcachedClient is no available connection at this moment###");
        }
        return keyExists;
    }

    /**
     * 更新 Memcached 数据
     *
     * @param cacheKey
     * @param cacheValue
     * @return
     * @throws Exception
     */
    public boolean replaceCacheNode(String cacheKey, Object cacheValue) throws Exception {
        log.debug("--- replaceCacheNode() start ---");
        /**boolean repType = memcachedClient.replace(cacheKey, MemcachedConstant.EXPIRATION_TIME, cacheValue);*/
        boolean repType = this.retType;
        try {
            repType = cas(cacheKey, cacheValue);
        } catch (Exception e) {
            log.error("###MemcachedClient is no available connection at this moment###");
        }
        return repType;
    }

    //原子更新 Memcached 数据
    public boolean cas(java.lang.String key, java.lang.Object value) throws Exception {

        GetsResponse<Integer> result;
        try {
            result = memcachedClient.gets(key);
            if (null != result) {
                long cas = result.getCas();
                return memcachedClient.cas(key, EXPIRATION_TIME, value, cas);
            } else {
                return setCacheNode(key, value);
            }
        } catch (TimeoutException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (MemcachedException e) {
            e.printStackTrace();
        } catch (Exception e) {
            //e.printStackTrace();
            log.error("###MemcachedClient is no available connection at this moment###");
        }
        return false;
    }

    /**
     * 删除 Memcached 数据
     *
     * @param cacheKey
     * @return
     * @throws Exception
     */
    public boolean removeCacheNode(String cacheKey) throws Exception {
        log.debug("--- removeCacheNode() start ---");
        boolean delType = this.retType;
        try {
            delType = memcachedClient.delete(cacheKey);
        } catch (Exception e) {
            log.error("###MemcachedClient is no available connection at this moment###");
        }
        return delType;
    }
}